package com.finance.framework.qurtz;

import com.finance.framework.lang.Page;
import com.finance.scheduler.service.QuartzManager;
import com.finance.system.bean.JobStateDesciptor;
import org.apache.commons.collections.CollectionUtils;
import org.quartz.SchedulerException;
import org.quartz.TriggerKey;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.SmartLifecycle;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by CBWL on 2017/6/5.
 */
public class RunningStatusAcquirer implements SmartLifecycle {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private boolean autoStartup = true;
    private boolean isRunning = false;
    private int phase = 2147483646;//此值比org.springframework.scheduling.quartz.SchedulerFactoryBean对应值小1个单位
    private ReentrantLock createQueueLock = new ReentrantLock();
    private ReentrantLock blockingQueueMapLock = new ReentrantLock();
    private Map<TriggerKey, PageBlockingQueue> blockingQueueMap = new ConcurrentHashMap<TriggerKey, PageBlockingQueue>();
    private AutowireCapableBeanFactory autowireCapableBeanFactory;
    private RunningStatusSource runningStatusSource;
    private QuartzManager quartzManager;

    public void setAutowireCapableBeanFactory(AutowireCapableBeanFactory autowireCapableBeanFactory){
        this.autowireCapableBeanFactory = autowireCapableBeanFactory;
    }

    public void setRunningStatusSource(RunningStatusSource runningStatusSource){
        this.runningStatusSource = runningStatusSource;
    }

    public void setQuartzManager(QuartzManager quartzManager){
        this.quartzManager = quartzManager;
    }

    @Deprecated
    public  Page acquirePage(TriggerKey triggerKey){
        this.logger.info("RunningStatusAcquirer:acquire ");
        PageBlockingQueue queue = this.getQueue(triggerKey);
        try {
            return queue.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }

    public  Page acquirePage(TriggerKey triggerKey,TimeUnit timeUnit,long time){
        this.logger.info("RunningStatusAcquirer:acquire ");
        PageBlockingQueue queue = this.getQueue(triggerKey);
        try {
            return queue.get(timeUnit,time);
        } catch (InterruptedException e) {
            this.logger.error(e.getMessage(),e);
            // Restore the interrupted status
            Thread.currentThread().interrupt();
        }
        return null;
    }

    public  void putback(TriggerKey triggerKey,Page page){
        this.logger.info("RunningStatusAcquirer:putback ");
        PageBlockingQueue queue = this.getQueue(triggerKey);
        queue.put(page);
        //TODO 此处需要将queue对象持久化到DB中
    }

    public  void rebuildQueueMap(TriggerKey triggerKey, PageBlockingQueue queue){
        blockingQueueMapLock.lock();
        this.blockingQueueMap.put(triggerKey,queue);
        blockingQueueMapLock.unlock();
     }

    public  PageBlockingQueue acquireQueue(TriggerKey triggerKey){
        PageBlockingQueue pageBlockingQueue = this.getQueue(triggerKey);
        return pageBlockingQueue;
    }

    public Map<TriggerKey, PageBlockingQueue> getAllInfo(){
        return this.blockingQueueMap;
    }

    @Override
    public boolean isAutoStartup() {
        return this.autoStartup;
    }

    @Override
    public void stop(Runnable runnable) {
        runnable.run();
        this.isRunning = false;
    }

    @Override
    public void start() {
        isRunning = true;
        List<JobStateDesciptor> list = null;
        try {
            list = this.quartzManager.getAllJobStateDesciptor();
        } catch (SchedulerException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        if(CollectionUtils.isNotEmpty(list)){
            for(JobStateDesciptor jobStateDesciptor : list){
            PageBlockingQueue queue = this.autowireCapableBeanFactory.createBean(PageBlockingQueue.class);
                this.rebuildQueueMap(new TriggerKey(jobStateDesciptor.getTriggerName(),jobStateDesciptor.getTriggerGroupName()),queue);
            }
        }
    }

    @Override
    public void stop() {
        this.isRunning = false;
    }

    @Override
    public boolean isRunning() {
        return this.isRunning;
    }

    @Override
    public int getPhase() {
        return this.phase;
    }

    private PageBlockingQueue getQueue(TriggerKey triggerKey){
        blockingQueueMapLock.lock();
        PageBlockingQueue queue = blockingQueueMap.get(triggerKey);
        if(queue == null){
            try{
                createQueueLock.lock();
                this.logger.info("queue is null ,to create");
                queue = blockingQueueMap.get(triggerKey);
                this.logger.info("queue is not null ,skip");
                if (queue == null) {
                    this.logger.info("queue is  created");
                    queue = this.autowireCapableBeanFactory.createBean(PageBlockingQueue.class);
                    blockingQueueMap.put(triggerKey, queue);
                    //TODO 此处需要将queue对象持久化到DB中
                }
            }catch (Exception e){
                this.logger.error(e.getMessage(),e);
            }finally {
                if(createQueueLock.isLocked()) {
                    createQueueLock.unlock();
                }
            }
        }
        blockingQueueMapLock.unlock();
        return queue;
     }
}
